﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Windows;
using Core.Settings;
using Extraction;

namespace Settings.Forms
{
    public class PdfFileConverter
    {
        private static readonly char[] Comma = new[] { ',' };
        private static readonly char[] Space = new[] { ' ' };
        private static readonly char[] Slash = new[] { '/' };

        public PdfFileConverter()
            : this("pdfParseTemplate.xml")
        {
        }

        public PdfFileConverter(string template)
        {
            PdfParseTemplate = template;
        }

        public string PdfParseTemplate { get; private set; }
        public void UpdateFromPdf(string pdfFile, PageSettings pageSet)
        {
            var template = GetFormularData(pdfFile);

            foreach (var field in template.Fields)
            {
                var fieldSetting = pageSet.Fields.Single(f => f.ElementID == field.ElementID);
                UpdateFieldSettingValue(fieldSetting, field);
            }
        }

        public FormularData GetFormularData(string pdfFile)
        {
            var template = GetTemplate();

            ExtractDataIntoTemplate(pdfFile, template);
            return template;
        }

        private void UpdateFieldSettingValue(FieldSettings fieldSetting, Field field)
        {
            switch (fieldSetting.InputType)
            {
                case "text":
                    fieldSetting.InputValue = ExtractValue(field.ElementID, field.Value);
                    break;
                case "radio":
                    fieldSetting.Checked = field.Value.Contains("X"); break;
                case "select":
                    fieldSetting.InputValue = ConvertSelectValue(field.Value.Trim()); break;
                case "checkbox":
                    if (fieldSetting.ElementID == "opiekunowie_chkNieDotyczy")
                        fieldSetting.Checked = string.IsNullOrEmpty(field.Value); break;

            }
        }

        private static readonly Func<string, int, string> commaExtract = (input, index) => input.Split(Comma)[index].Trim();
        private static readonly Func<string, int, string> slashExtract = (input, index) =>
                                                                             {
                                                                                 var splitted = input.Split(Slash);
                                                                                 return splitted.Length > index ? splitted[index].Trim() : string.Empty;
                                                                             };
        private static readonly Func<string, int, string> commaExtractSkipFirst = (input, count) => string.Join(",", input.Split(Comma).Skip(count).ToArray());
        private static readonly Func<string, int, string> spaceExtract = (input, index) => input.Split(Space)[index].Trim();
        private static readonly Func<string, string> spaceExtractWithoutLast = input =>
        {
            var splitted = input.Split(Space);
            return string.Join(" ", splitted.Take(splitted.Length - 1).ToArray());
        };

        private static readonly Func<string, string> spaceExtractLast = input =>
        {
            var splitted = input.Split(Space);
            return splitted[splitted.Length - 1].Trim();
        };
        private static readonly Dictionary<string, Func<string, string>> valueExtracts =
            new Dictionary<string, Func<string, string>>
                {
                    {"opiekunowie_txtImie1", input=>commaExtract(input,0)},
                    {"opiekunowie_txtNazwisko1", input=>commaExtract(input,1)},
                    {"opiekunowie_txtStanProwincja1", input=>commaExtract(input,0)},
                    {"opiekunowie_txtMiejscowosc1", input=>spaceExtract(commaExtract(input,1),1)},
                    {"opiekunowie_txtKod1", input=>spaceExtract(commaExtract(input,1),0)},
                    {"opiekunowie_txtAdres1", input=>commaExtractSkipFirst(input,2)},

                    {"txt45Miejscowosc", input=>commaExtract(input,0)},
                    {"txt45Adres", input=>commaExtractSkipFirst(input,1)},
                    {"txt46TelefonPrefiks0", input=>spaceExtract(input,0)},
                    {"txt46TelefonNumer0", input=>spaceExtract(input,1)},
                    {"txt20gPrefix", input=>spaceExtract(input,0)},
                    {"txt20hTelefon", input=>spaceExtract(input,1)},
                    {"txt20PrefiksFax", input=>spaceExtract(input,0)},
                    {"txt20NumerFax", input=>spaceExtract(input,1)},

                    {"txt20cStanProwincja", input=>commaExtract(input,1)},
                    {"txt20dMiejscowosc", input=>spaceExtract(commaExtract(input,2),1)},
                    {"txt20eKodPocztowy", input=>spaceExtract(commaExtract(input,2),0)},
                    {"txt20fAdres", input=>commaExtractSkipFirst(input,3)},

                    {"ctrl31__txt34miejscowosc", input=>spaceExtract(commaExtract(input,1),1)},
                    {"ctrl31__txt34kod", input=>spaceExtract(commaExtract(input,1),0)},
                    {"ctrl31__txt34adres", input=>spaceExtractWithoutLast(commaExtract(input,2))},
                    {"ctrl31__txt34NumerDomu", input=>slashExtract(spaceExtractLast(commaExtract(input,2)),0)},
                    {"ctrl31__txt34NumerLokalu", input=>slashExtract(spaceExtractLast(commaExtract(input,2)),1)},
                    {"ctrl31__txt34prefikstel", input=>spaceExtract(input,0)},
                    {"ctrl31__txt34tel", input=>spaceExtract(input,1)},
                    {"ctrl31__txt34prefiksfax", input=>spaceExtract(input,0)},
                    {"ctrl31__txt34fax", input=>spaceExtract(input,1)},
                };
        private string ExtractValue(string elementID, string value)
        {
            if (valueExtracts.ContainsKey(elementID) && string.IsNullOrEmpty(value) == false)
                return valueExtracts[elementID](value.Trim(new char[] { ',', '.' })).Trim();
            return value.Trim(new char[] { ',', '.', ' ' });
        }

       private string ConvertSelectValue(string value)
        {
            if (SelectValuesConvertions.ContainsKey(value))
                return SelectValuesConvertions[value];

            return string.Empty;
        }

        private static void ExtractDataIntoTemplate(string pdfFile, FormularData template)
        {
            var parsedArea = new Rect(47, 86, 360, 620);
            var extractor = new WordExtractor();
            foreach (var group in template.Fields.GroupBy(f => f.Page))
            {
                var lines = extractor.Extract(pdfFile, group.Key, parsedArea).ToList();
                foreach (var field in group)
                {
                    var words = lines.ForRectExact(new Rect(field.X, field.Y, field.Width, field.Height))
                        .Select(l => l.ToString())
                        .ToArray();
                    field.Value = string.Join(" ", words);
                }
            }
        }


        private FormularData GetTemplate()
        {
            using (Stream stream = File.OpenRead(PdfParseTemplate))
            {
                var serializer = new DataContractSerializer(typeof(FormularData));
                var template = (FormularData)serializer.ReadObject(stream);
                return template;
            }
        }

   
        private static readonly Dictionary<string, string> SelectValuesConvertions = new Dictionary<string, string>
        {
            { "БЕЛАРУСЬ", "BLR" },
            {"Административно-судебный служащий","35"},
            {"Артист","05"},
            {"Архитектор","02"},
            {"Банкир","06"},
            {"Без профессии","30"},
            {"Водитель","10"},
            {"Государственный служащий","15"},
            {"Дипломат","32"},
            {"Духовное лицо, монахиня","09"},
            {"Журналист","21"},
            {"Информатик","17"},
            {"Иные","99"},
            {"Коммерсант","07"},
            {"Личный ассистент дипломата","34"},
            {"Медицинские профессии","22"},
            {"Менеджер","08"},
            {"Мода, косметика","26"},
            {"Моряк","23"},
            {"Научный исследователь","12"},
            {"Пенсионер","28"},
            {"Персонал дипломатической администрации","33"},
            {"Политик","16"},
            {"Полицейский, солдат","27"},
            {"Предприниматель, занятый собственным делом","25"},
            {"Ремесленник","03"},
            {"Спортсмен, тренер","29"},
            {"Студент, практикант, стажер","31"},
            {"Техник иной","20"},
            {"Умственный работник","14"},
            {"Учитель","13"},
            {"Фермер","01"},
            {"Физический работник","24"},
            {"Химик","19"},
            {"Член правления фирмы","36"},
            {"Электрик","18"},
            {"Юрист","04"}};
    }
}